import 'dart:async';
import 'dart:isolate';

class Task {
  final String id;
  final int priority; // 数值越小，优先级越高
  final Future<void> Function() job; // 任务执行函数

  Task({
    required this.id,
    required this.priority,
    required this.job,
  });

  @override
  String toString() {
    return 'Task(id: $id, priority: $priority)';
  }
}

class PriorityTaskQueue {
  final List<Task> _heap = [];

  void enqueue(Task task) {
    _heap.add(task);
    _heapifyUp(_heap.length - 1);
  }

  Task? dequeue() {
    if (_heap.isEmpty) return null;
    Task topTask = _heap[0];
    Task lastTask = _heap.removeLast();
    if (_heap.isNotEmpty) {
      _heap[0] = lastTask;
      _heapifyDown(0);
    }
    return topTask;
  }

  Task? peek() => _heap.isEmpty ? null : _heap[0];

  bool get isEmpty => _heap.isEmpty;
  int get length => _heap.length;

  void _heapifyUp(int index) {
    while (index > 0) {
      int parentIndex = (index - 1) ~/ 2;
      if (_heap[index].priority >= _heap[parentIndex].priority) break;
      _swap(index, parentIndex);
      index = parentIndex;
    }
  }

  void _heapifyDown(int index) {
    int lastIndex = _heap.length - 1;
    while (true) {
      int leftChildIndex = 2 * index + 1;
      int rightChildIndex = 2 * index + 2;
      int smallestIndex = index;

      if (leftChildIndex <= lastIndex &&
          _heap[leftChildIndex].priority < _heap[smallestIndex].priority) {
        smallestIndex = leftChildIndex;
      }
      if (rightChildIndex <= lastIndex &&
          _heap[rightChildIndex].priority < _heap[smallestIndex].priority) {
        smallestIndex = rightChildIndex;
      }
      if (smallestIndex == index) break;
      _swap(index, smallestIndex);
      index = smallestIndex;
    }
  }

  void _swap(int i, int j) {
    Task temp = _heap[i];
    _heap[i] = _heap[j];
    _heap[j] = temp;
  }
}

class PreemptiveTaskExecutor {
  final PriorityTaskQueue _queue = PriorityTaskQueue();
  final Map<String, _IsolateController> _activeIsolates = {}; // id -> controller
  final List<Task> _preemptedTasks = []; // 栈结构存储被抢占的任务

  Future<void> addTask(Task task) {
    final completer = Completer<void>();
    _queue.enqueue(task);

    _checkForPreemption();
    return completer.future;
  }

  void _checkForPreemption() {
    Task? highestPriorityTask = _queue.peek();
    Task? currentTask = _activeIsolates.isNotEmpty
        ? _activeIsolates.values.first.task // 简化：假设单任务执行
        : null;

    if (currentTask != null &&
        highestPriorityTask != null &&
        highestPriorityTask.priority < currentTask.priority) {
      _preemptCurrentTask();
    }

    if (_activeIsolates.isEmpty) {
      _executeNextTask();
    }
  }

  void _preemptCurrentTask() {
    if (_activeIsolates.isEmpty) return;

    // 获取当前正在执行的任务（假设单任务执行）
    var entry = _activeIsolates.entries.first;
    String currentTaskId = entry.key;
    _IsolateController controller = entry.value;

    // 杀死当前任务的Isolate
    controller.isolate.kill(priority: Isolate.immediate);
    // controller.completer.completeError(
    //     TaskPreemptedException('Task $currentTaskId was preempted'));

    // 从活动列表移除并存入抢占栈
    Task preemptedTask = controller.task;
    _activeIsolates.remove(currentTaskId);
    _preemptedTasks.add(preemptedTask);

    print('Task ${preemptedTask.id} (priority ${preemptedTask.priority}) preempted.');
  }

  Future<void> _executeNextTask() async {
    if (_queue.isEmpty) return;

    Task task = _queue.dequeue()!;
    final completer = Completer<void>();
    final receivePort = ReceivePort();

    try {
      // 在新的Isolate中执行任务
      Isolate isolate = await Isolate.spawn(
        _isolateEntryPoint,
        _IsolateMessage(
          sendPort: receivePort.sendPort,
          task: task,
        ),
      );

      _activeIsolates[task.id] = _IsolateController(isolate, completer, task);

      receivePort.listen((message) {
        if (message is _IsolateResult) {
          if (message.success) {
            completer.complete();
          } else {
            completer.completeError(message.error!);
          }
          _cleanUpIsolate(task.id, isolate);
          _executeNextTask(); // 执行下一个任务
        }
      });
    } catch (e) {
      completer.completeError(e);
      _activeIsolates.remove(task.id);
      _executeNextTask();
    }
  }

  void _cleanUpIsolate(String taskId, Isolate isolate) {
    isolate.kill(priority: Isolate.immediate);
    _activeIsolates.remove(taskId);
  }

  // 尝试重新执行上次被抢占的任务
  void _resumePreemptedTask() {
    if (_preemptedTasks.isEmpty) return;
    Task taskToResume = _preemptedTasks.removeLast();
    addTask(taskToResume);
  }
}

// Isolate 入口点
void _isolateEntryPoint(_IsolateMessage message) async {
  final SendPort sendPort = message.sendPort;
  final Task task = message.task;

  try {
    await task.job(); // 执行实际任务
    sendPort.send(_IsolateResult(success: true));
  } catch (error, stackTrace) {
    sendPort.send(_IsolateResult(success: false, error: error, stackTrace: stackTrace));
  }
}

// 用于与Isolate通信的消息类
class _IsolateMessage {
  final SendPort sendPort;
  final Task task;
  _IsolateMessage({required this.sendPort, required this.task});
}

// Isolate执行结果
class _IsolateResult {
  final bool success;
  final dynamic error;
  final StackTrace? stackTrace;
  _IsolateResult({required this.success, this.error, this.stackTrace});
}

// 用于控制Isolate的类
class _IsolateController {
  final Isolate isolate;
  final Completer<void> completer;
  final Task task;
  _IsolateController(this.isolate, this.completer, this.task);
}

// 任务被抢占的异常
class TaskPreemptedException implements Exception {
  final String message;
  TaskPreemptedException(this.message);
  @override
  String toString() => 'TaskPreemptedException: $message';
}

void main() async {
  final executor = PreemptiveTaskExecutor();

  // 添加一个长时间运行的低优先级任务
  executor.addTask(Task(
    id: 'task-low',
    priority: 5,
    job: () async {
      print('Low-priority task started.');
      await Future.delayed(Duration(seconds: 10)); // 模拟耗时操作
      print('Low-priority task completed.');
    },
  ));

  // 稍后添加一个高优先级任务
  await Future.delayed(Duration(seconds: 2));
  executor.addTask(Task(
    id: 'task-high',
    priority: 1, // 优先级数值更低，更高
    job: () async {
      print('High-priority task started.');
      await Future.delayed(Duration(seconds: 2));
      print('High-priority task completed.');
    },
  ));

  // 再添加一个中优先级任务
  await Future.delayed(Duration(seconds: 1));
  executor.addTask(Task(
    id: 'task-medium',
    priority: 3,
    job: () async {
      print('Medium-priority task started.');
      await Future.delayed(Duration(seconds: 3));
      print('Medium-priority task completed.');
    },
  ));
}